package org.jeecg.modules.system.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.api.entity.SysPermission;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.PermissionVo;
import org.jeecg.common.util.Md5Util;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.platform.organization.service.ICyPlatformOrganizationInfoService;
import org.jeecg.modules.platform.organization.service.ICyPlatformOrganizationPermissionService;
import org.jeecg.modules.system.entity.CyHomeManage;
import org.jeecg.modules.system.entity.SysRoleIndex;
import org.jeecg.modules.system.mapper.CyHomeManageMapper;
import org.jeecg.modules.system.service.ICyHomeManageService;
import org.jeecg.modules.system.service.ISysPermissionService;
import org.jeecg.modules.system.util.PermissionDataUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Description: 首页管理
 * @Author: jeecg-boot
 * @Date:   2024-12-09
 * @Version: V1.0
 */
@Service
public class CyHomeManageServiceImpl extends ServiceImpl<CyHomeManageMapper, CyHomeManage> implements ICyHomeManageService {

    /**
     * 注入底层通用接口
     */
    @Autowired
    private ISysBaseAPI sysBaseAPI;

    @Autowired
    private ISysPermissionService sysPermissionService;

    @Autowired
    @Lazy
    private ICyPlatformOrganizationInfoService organizationInfoService;

    @Autowired
    private ICyPlatformOrganizationPermissionService orgPermissionService;

    Pattern pattern = Pattern.compile(".*(?:module_admin|isystem|domianURL|online|jeecg).*");

    /**
     * 子菜单
     */
    private static final String CHILDREN = "children";
    @Override
    public Result<?> getPermission() {

        Result<JSONObject> result = new Result<JSONObject>();
        try {
            //直接获取当前用户不适用前端token
            LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            if (oConvertUtils.isEmpty(loginUser)) {
                return Result.error("请登录系统！");
            }
            List<SysPermission> metaList = sysPermissionService.queryByUser(loginUser.getUsername());

            // 获取组织当前状态对应权限
            List<String> permissionList = organizationInfoService.getPermissionList(loginUser.getOrganizationId());

            if (CollectionUtil.isNotEmpty(permissionList)) {
                // 过滤掉组织当前状态未授权的信息
                metaList = metaList.stream()
                        .filter(meta -> permissionList.contains(meta.getId())
                                || StringUtils.isBlank(meta.getUrl()) || pattern.matcher(meta.getUrl()).matches())
                        .collect(Collectors.toList());
            }

            JSONObject json = new JSONObject();
            JSONArray menujsonArray = new JSONArray();

            List<PermissionVo> newMetaList = new ArrayList<>();

            for (SysPermission sysPermission : metaList) {
                PermissionVo permissionVo = new PermissionVo();
                BeanUtils.copyProperties(sysPermission, permissionVo);
                newMetaList.add(permissionVo);
            }

            // 获得已经添加的菜单
            List<CyHomeManage> homeManageList = getList();
            for (CyHomeManage homeManage : homeManageList){
                boolean select = false;
                for (PermissionVo permission : newMetaList){
                    // 如果 ID 一样,则需要设定为已选中
                    if (permission.getId().equals(homeManage.getMenuId())){
                        select = true;
                        permission.setTest(select);
                    }
                }
                if (!select){
                    // 如果该ID不存在有的权限中,则删除
                    LambdaQueryWrapper<CyHomeManage> queryWrapper = Wrappers.lambdaQuery();
                    queryWrapper.eq(CyHomeManage::getMenuId,homeManage.getMenuId());
                    remove(queryWrapper);
                }
            }

            this.getPermissionJsonArray(menujsonArray,newMetaList, null);
            //一级菜单下的子菜单全部是隐藏路由，则一级菜单不显示
            this.handleFirstLevelMenuHidden(menujsonArray);

            removeMenu(menujsonArray);
            // 获取组织授权菜单
            List<String> moduleList = orgPermissionService.listModulesByOrg(loginUser.getOrganizationId());
            // 过滤组织未授权的模块
            List<Object> menuList = PermissionDataUtil.filterPermission(menujsonArray, moduleList);
            //路由菜单
            json.put("menu", menuList);
            result.setResult(json);
        } catch (Exception e) {
            result.error500("查询失败:" + e.getMessage());
            log.error(e.getMessage(), e);
        }
        return Result.ok(result) ;

    }
    public List<CyHomeManage> getList() {
        //直接获取当前用户不适用前端token
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<CyHomeManage> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(CyHomeManage::getCreateBy,loginUser.getUsername());
        return list(queryWrapper);
    }

    public Boolean saveData(List<CyHomeManage> saveList) {
        //直接获取当前用户不适用前端token
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<CyHomeManage> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(CyHomeManage::getUserId,loginUser.getId());
        remove(queryWrapper);
        for (int i = 0; i < saveList.size(); i++) {
            saveList.get(i).setUserId(loginUser.getId());
            saveList.get(i).setSort(i);
        }
        return saveOrUpdateBatch(saveList);
    }


    /**
     *  获取菜单JSON数组
     * @param jsonArray
     * @param metaList
     * @param parentJson
     */
    private void getPermissionJsonArray(JSONArray jsonArray, List<PermissionVo> metaList, JSONObject parentJson) {
        for (PermissionVo permission : metaList) {
            if (permission.getMenuType() == null) {
                continue;
            }
            String tempPid = permission.getParentId();
            JSONObject json = getPermissionJsonObject(permission);
            if(json==null) {
                continue;
            }
            if (parentJson == null && oConvertUtils.isEmpty(tempPid)) {
                jsonArray.add(json);
                if (!permission.isLeaf()) {
                    getPermissionJsonArray(jsonArray, metaList, json);
                }
            } else if (parentJson != null && oConvertUtils.isNotEmpty(tempPid) && tempPid.equals(parentJson.getString("id"))) {
                // 类型( 0：一级菜单 1：子菜单 2：按钮 )
                if (permission.getMenuType().equals(CommonConstant.MENU_TYPE_2)) {
                    JSONObject metaJson = parentJson.getJSONObject("meta");
                    if (metaJson.containsKey("permissionList")) {
                        metaJson.getJSONArray("permissionList").add(json);
                    } else {
                        JSONArray permissionList = new JSONArray();
                        permissionList.add(json);
                        metaJson.put("permissionList", permissionList);
                    }
                    // 类型( 0：一级菜单 1：子菜单 2：按钮 )
                } else if (permission.getMenuType().equals(CommonConstant.MENU_TYPE_1) || permission.getMenuType().equals(CommonConstant.MENU_TYPE_0)) {
                    if (parentJson.containsKey("children")) {
                        parentJson.getJSONArray("children").add(json);
                    } else {
                        JSONArray children = new JSONArray();
                        children.add(json);
                        parentJson.put("children", children);
                    }

                    if (!permission.isLeaf()) {
                        getPermissionJsonArray(jsonArray, metaList, json);
                    }
                }
            }

        }
    }


    /**
     * 删除部分菜单
     * @param menujsonArray 菜单数组
     */
    private void removeMenu(JSONArray menujsonArray) {
        // 需要排除的菜单
//        List<String> removeMenuList = Arrays.asList("首页","管理员模块","管理平台","组织管理","产品碳足迹","组织碳盘查","碳排放因子库");
        List<String> removeMenuList = Arrays.asList("首页","管理员模块");

        for (int i = 0; i < menujsonArray.size(); i++) {
            JSONObject menuObject = (JSONObject) menujsonArray.get(i);
            String title = menuObject.getJSONObject("meta").get("title").toString();

            if (removeMenuList.contains(title)){
                menujsonArray.remove(i);
                i--;
            }
        }
    }


    /**
     * 根据菜单配置生成路由json
     * @param permission
     * @return
     */
    private JSONObject getPermissionJsonObject(PermissionVo permission) {
        JSONObject json = new JSONObject();
        json.put("homeIcon", permission.getHomeIcon());
        json.put("select", permission.isTest());
        // 类型(0：一级菜单 1：子菜单 2：按钮)
        if (permission.getMenuType().equals(CommonConstant.MENU_TYPE_2)) {
            //json.put("action", permission.getPerms());
            //json.put("type", permission.getPermsType());
            //json.put("describe", permission.getName());
            return null;
        } else if (permission.getMenuType().equals(CommonConstant.MENU_TYPE_0) || permission.getMenuType().equals(CommonConstant.MENU_TYPE_1)) {
            json.put("id", permission.getId());
            if (permission.isRoute()) {
                //表示生成路由
                json.put("route", "1");
            } else {
                //表示不生成路由
                json.put("route", "0");
            }

            if (isWwwHttpUrl(permission.getUrl())) {
                json.put("path", Md5Util.md5Encode(permission.getUrl(), "utf-8"));
            } else {
                json.put("path", permission.getUrl());
            }

            // 重要规则：路由name (通过URL生成路由name,路由name供前端开发，页面跳转使用)
            if (oConvertUtils.isNotEmpty(permission.getComponentName())) {
                json.put("name", permission.getComponentName());
            } else {
                json.put("name", urlToRouteName(permission.getUrl()));
            }

            JSONObject meta = new JSONObject();
            // 是否隐藏路由，默认都是显示的
            if (permission.isHidden()) {
                json.put("hidden", true);
                //vue3版本兼容代码
                meta.put("hideMenu",true);
            }
            // 聚合路由
            if (permission.isAlwaysShow()) {
                json.put("alwaysShow", true);
            }
            json.put("component", permission.getComponent());
            // 由用户设置是否缓存页面 用布尔值
            if (permission.isKeepAlive()) {
                meta.put("keepAlive", true);
            } else {
                meta.put("keepAlive", false);
            }

            /*update_begin author:wuxianquan date:20190908 for:往菜单信息里添加外链菜单打开方式 */
            //外链菜单打开方式
            if (permission.isInternalOrExternal()) {
                meta.put("internalOrExternal", true);
            } else {
                meta.put("internalOrExternal", false);
            }
            /* update_end author:wuxianquan date:20190908 for: 往菜单信息里添加外链菜单打开方式*/

            meta.put("title", permission.getName());

            //update-begin--Author:scott  Date:20201015 for：路由缓存问题，关闭了tab页时再打开就不刷新 #842
            String component = permission.getComponent();
            if(oConvertUtils.isNotEmpty(permission.getComponentName()) || oConvertUtils.isNotEmpty(component)){
                meta.put("componentName", oConvertUtils.getString(permission.getComponentName(),component.substring(component.lastIndexOf("/")+1)));
            }
            //update-end--Author:scott  Date:20201015 for：路由缓存问题，关闭了tab页时再打开就不刷新 #842

            if (oConvertUtils.isEmpty(permission.getParentId())) {
                // 一级菜单跳转地址
                json.put("redirect", permission.getRedirect());
                if (oConvertUtils.isNotEmpty(permission.getIcon())) {
                    meta.put("icon", permission.getIcon());
                }
            } else {
                if (oConvertUtils.isNotEmpty(permission.getIcon())) {
                    meta.put("icon", permission.getIcon());
                }
            }
            if (isWwwHttpUrl(permission.getUrl())) {
                meta.put("url", permission.getUrl());
            }
            // update-begin--Author:sunjianlei  Date:20210918 for：新增适配vue3项目的隐藏tab功能
            if (permission.isHideTab()) {
                meta.put("hideTab", true);
            }
            // update-end--Author:sunjianlei  Date:20210918 for：新增适配vue3项目的隐藏tab功能
            json.put("meta", meta);
        }

        return json;
    }

    /**
     * 判断是否外网URL 例如： http://localhost:8080/jeecg-boot/swagger-ui.html#/ 支持特殊格式： {{
     * window._CONFIG['domianURL'] }}/druid/ {{ JS代码片段 }}，前台解析会自动执行JS代码片段
     *
     * @return
     */
    private boolean isWwwHttpUrl(String url) {
        boolean flag = url != null && (url.startsWith(CommonConstant.HTTP_PROTOCOL) || url.startsWith(CommonConstant.HTTPS_PROTOCOL) || url.startsWith(SymbolConstant.DOUBLE_LEFT_CURLY_BRACKET));
        if (flag) {
            return true;
        }
        return false;
    }

    /**
     * 通过URL生成路由name（去掉URL前缀斜杠，替换内容中的斜杠‘/’为-） 举例： URL = /isystem/role RouteName =
     * isystem-role
     *
     * @return
     */
    private String urlToRouteName(String url) {
        if (oConvertUtils.isNotEmpty(url)) {
            if (url.startsWith(SymbolConstant.SINGLE_SLASH)) {
                url = url.substring(1);
            }
            url = url.replace("/", "-");

            // 特殊标记
            url = url.replace(":", "@");
            return url;
        } else {
            return null;
        }
    }


    /**
     * 一级菜单的子菜单全部是隐藏路由，则一级菜单不显示
     *
     * @param jsonArray
     */
    private void handleFirstLevelMenuHidden(JSONArray jsonArray) {
        jsonArray = jsonArray.stream().map(obj -> {
            JSONObject returnObj = new JSONObject();
            JSONObject jsonObj = (JSONObject) obj;
            if (jsonObj.containsKey(CHILDREN)) {
                JSONArray childrens = jsonObj.getJSONArray(CHILDREN);
                childrens = childrens.stream().filter(arrObj -> !"true".equals(((JSONObject) arrObj).getString("hidden"))).collect(Collectors.toCollection(JSONArray::new));
                if (childrens == null || childrens.size() == 0) {
                    jsonObj.put("hidden", true);

                    //vue3版本兼容代码
                    JSONObject meta = new JSONObject();
                    meta.put("hideMenu", true);
                    jsonObj.put("meta", meta);
                }
            }
            return returnObj;
        }).collect(Collectors.toCollection(JSONArray::new));
    }
}
